home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume13 / iface / part01 next >
Encoding:
Internet Message Format  |  1988-01-30  |  18.9 KB

  1. Subject:  v13i063:  Generic user interface kit, Part01/02
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Marc Majka <majka@ubc.csnet>
  7. Posting-number: Volume 13, Issue 63
  8. Archive-name: iface/part01
  9.  
  10. [  This uses BSD tty driver, and will take a bit of grundge to port it
  11.    to SystemV, let alone Version7.  --r$ ]
  12.  
  13. This package contains a "generic" user interface which may be useful.
  14. It provides word completion, CBREAK I/O, and keybinding.  It is
  15. reasonably easy to tailor to an application.  The distributed
  16. version compiles and runs, and contains a couple of functions
  17. which demonstrate the flavour of the interface.  Cut on the line
  18. and feed to "sh". It will create the directory "iface" and put
  19. everything in there.
  20.  
  21. Manifest:
  22. comc.c   - word completion routine
  23. exec.c   - executive-type functions
  24. iface.h  - header stuff
  25. fns.c    - example functions to demo iface
  26. init.c   - initialization routines
  27. io.c     - input/output routines
  28. iface.c  - main routine
  29. Makefile - to compile it
  30. README   - describes what it is and how it works
  31.  
  32. ---
  33. Marc Majka
  34.  
  35.  
  36. - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - -
  37. #! /bin/sh
  38. # This is a shell archive, meaning:
  39. # 1. Remove everything above the #! /bin/sh line.
  40. # 2. Save the resulting text in a file.
  41. # 3. Execute the file with /bin/sh (not csh) to create the files:
  42. #    iface
  43. export PATH; PATH=/bin:$PATH
  44. if test ! -d 'iface'
  45. then
  46.     mkdir 'iface'
  47. fi
  48. cd 'iface'
  49. if test -f 'comc.c'
  50. then
  51.     echo shar: will not over-write existing file "'comc.c'"
  52. else
  53. cat << \SHAR_EOF > 'comc.c'
  54. /*
  55.     getcom: get a command (character string) from standard input
  56.     getcom takes a list of character strings in the same format
  57.     as that used for argv, and a count of the number of strings
  58.     in the list, as in argc.  It does EMACS-style string
  59.     completion.  Getcom returns as its value, the index of the
  60.     command.  -1 is returned if the user aborts the completion.
  61.     Note that the command list "clist" must contain its strings
  62.     in sorted order.  Also note that getcom expects to have the
  63.     terminal in raw or cbreak mode, with no character echoing.
  64.  
  65.     Characters are read and appended to a command string "cmd".
  66.     Certain characters have special meanings:
  67.  
  68.     ? causes getcom to print all possible completions
  69.     ^G and ESC abort and return -1
  70.     <space>, <tab>, and <return> cause getcom to complete
  71.     <linefeed> causes completion to the first possible string
  72.     <backspace> has the expected result
  73.     <DEL> is treated at <backspace>
  74.     ^U clears the cmd string and restarts completion
  75.  
  76. */
  77. #include <stdio.h>
  78.  
  79. getcom(clist,ncmd,prompt)
  80. char **clist;
  81. int ncmd;
  82. char *prompt;
  83. {
  84.     int cn,first,last,match,endpt,start,i,c;
  85.     char *entry,cmd[256];
  86.  
  87.     match = endpt = start = first = 0;
  88.     last = ncmd - 1;
  89.     cmd[0] = '\0';
  90.  
  91.     while (!match) {
  92.         c = getchar();
  93.  
  94.         switch(c) {
  95.  
  96.             case '?':
  97.                 match = try_match(&first,&last,&start,&endpt,&cn,clist,cmd);
  98.                 if (!match) {
  99.                     printf("\b \b\n\n");
  100.                     helpcom(clist,first,last);
  101.                     printf("\n%s %s",prompt,cmd);
  102.                 }
  103.                 else {
  104.                     entry = clist[cn];
  105.                     for (i = endpt; entry[i] != '\0'; i++)
  106.                         printf("%c",entry[i]);
  107.                 }
  108.                 break;
  109.  
  110.             case '\07': /* ^G */
  111.             case '\033': /* ESC */
  112.             case '\04': /* ^D */
  113.                 return(-1);
  114.  
  115.             case ' ': /* blank */
  116.             case '\t':  /* tab */
  117.             case '\r': /* return */
  118.                 match = try_match(&first,&last,&start,&endpt,&cn,clist,cmd);
  119.                 if (match) {
  120.                     entry = clist[cn];
  121.                     for (i = endpt; entry[i] != '\0'; i++)
  122.                         printf("%c",entry[i]);
  123.                 }
  124. /*                else printf("%c",7); */
  125.                 break;
  126.  
  127.             case '\n': /* newline */
  128.                 match = try_match(&first,&last,&start,&endpt,&cn,clist,cmd);
  129.                 if (!strcmp(clist[first],cmd)) {
  130.                     cn = first;
  131.                     match = 1;
  132.                 }
  133.                 if (!match) printf("%c",7);
  134.                 break;
  135.  
  136.             case '\b': /* backspace */
  137.             case 127:    /* DEL */
  138.                 if (endpt > 0) {
  139.                     printf("\b \b");
  140.                     endpt--;
  141.                     cmd[endpt] = '\0';
  142.                 }
  143.                 start = first = 0;
  144.                 last = ncmd - 1;
  145.                 break;
  146.  
  147.             case '\025':  /* ^U */
  148.                 for (i = 0; i < endpt; i++) printf("\b \b");
  149.                 match = endpt = start = first = 0;
  150.                 last = ncmd - 1;
  151.                 cmd[0] = '\0';
  152.                 break;
  153.  
  154.             default: /* anything else */
  155.                 printf("%c",c);
  156.                 cmd[endpt++] = c;
  157.                 cmd[endpt] = '\0';
  158.                 break;
  159.         }
  160.     }
  161.     return(cn);
  162. }
  163.  
  164. try_match(f,l,s,p,n,clist,cmd)
  165. int *f,*l,*s,*p,*n;
  166. char **clist,*cmd;
  167. {
  168.     int i,k,tf,tl;
  169.     char *fent,*lent;
  170.  
  171.     if (*p == 0) return(0);
  172.     tf = *f;
  173.     tl = *l;
  174.     k = *p + 1;
  175.     fent = clist[tf];
  176.     lent = clist[tl];
  177.  
  178.     for (i = *s + 1; i < k; i++) {
  179.         fent = clist[tf];
  180.         while ((tf < tl) && (strncmp(cmd,fent,i) > 0)) fent = clist[++tf];
  181.         lent = clist[tl];
  182.         while ((tl > tf) && (strncmp(cmd,lent,i) < 0)) lent = clist[--tl];
  183.     }
  184.  
  185.     if (tf == tl) {
  186.         if (strncmp(cmd,fent,*p) == 0) {
  187.             *f = tf; *l = tl; *s = *p; *n = tf;
  188.             return(1);
  189.         }
  190.         else {
  191.             i = *s;
  192.             while ((i < *p) && (cmd[i] == fent[i])) i++;
  193.             cmd[i] = '\0';
  194.             k = i;
  195.             for (; i < *p; i++) printf("\b \b");
  196.             *p = k;
  197.             return(0);
  198.         }
  199.     }
  200.     else {
  201.         i = *p;
  202.         while (fent[i] == lent[i]) {
  203.             cmd[i] = fent[i];
  204.             printf("%c",cmd[i++]);
  205.         }
  206.         cmd[i] = '\0';
  207.         *f = tf; *l = tl; *p = i; *s = *p;
  208.         return(0);
  209.     }
  210. }
  211.  
  212. helpcom(w,f,l)
  213. char **w;
  214. int f,l;
  215. {
  216.     int max, i, len, n;
  217.  
  218.     max = 0;
  219.     for (i = f; i <= l; i++) {
  220.         len = strlen(w[i]);
  221.         if (len > max) max = len;
  222.     }
  223.     n = (l - f) + 1;
  224.  
  225.     printf("? choose one of the following\n");
  226.     printlist(max,n,w+f);
  227.     printf("\n\n");
  228.     printf("? ? for command list\n");
  229.     printf("? ^D, ^G or ESC to exit, ^U to clear\n");
  230.     printf("? <space>, <tab> or <return> to complete\n");
  231.     printf("? <linefeed> to insist on first choice\n");
  232. }
  233.  
  234. printlist(size,items,list)
  235. int size,items;
  236. char *list[];
  237. {
  238.     int rows, cols, i, j, x, y, len, n;
  239.     char blank[256];
  240.  
  241.     for (i = 0; i < 256; i++) blank[i] = ' ';
  242.  
  243.     size += 1;
  244.  
  245.     cols = 79 / size;
  246.     rows = items / cols;
  247.     if (items > (rows * cols)) rows++;
  248.     cols = items / rows;
  249.     if (items > (rows * cols)) cols++;
  250.  
  251.     n = rows * cols;
  252.     y = -1;
  253.     x = 0;
  254.  
  255.     for (i = 0; i < n; i++) {
  256.         if (!(i % cols)) {
  257.             printf("\n");
  258.             y++;
  259.             x = y;
  260.         }
  261.         if (x < items) {
  262.             len = strlen(list[x]);
  263.             j = (size - len) + 1;
  264.             blank[j] = '\0';
  265.             printf("%s%s",list[x],blank);
  266.             blank[j] = ' ';
  267.         }
  268.         x += rows;
  269.     }
  270. }
  271.  
  272. SHAR_EOF
  273. fi # end of overwriting check
  274. if test -f 'exec.c'
  275. then
  276.     echo shar: will not over-write existing file "'exec.c'"
  277. else
  278. cat << \SHAR_EOF > 'exec.c'
  279. #include "iface.h"
  280.  
  281. print_version()
  282. {
  283.     int ref;
  284.  
  285.     ref = sym_ref("version");
  286.     printf("version %s\n",symbol[ref].strval);
  287. }
  288.  
  289. exec(ref)
  290. int ref;
  291. {
  292.     int (*comptr)();
  293.  
  294.     comptr = cptr[symbol[ref].value];
  295.     (*comptr)();
  296. }
  297.  
  298. ESC_prefix()
  299. {
  300.     int ref;
  301.  
  302.     lastkey = getchar();
  303.     ref = binding[lastkey][1];
  304.     exec(ref);
  305. }
  306.  
  307. CTL_X_prefix()
  308. {
  309.     int ref;
  310.  
  311.     lastkey = getchar();
  312.     ref = binding[lastkey][2];
  313.     exec(ref);
  314. }
  315.  
  316. CTL_Y_prefix()
  317. {
  318.     int ref;
  319.  
  320.     lastkey = getchar();
  321.     ref = binding[lastkey][3];
  322.     exec(ref);
  323. }
  324.  
  325. BOGUS()
  326. {
  327.     putchar('\07');
  328. }
  329.  
  330. quit()
  331. {
  332.     oldterm();
  333.     exit(0);
  334. }
  335.  
  336. oldterm()
  337. {
  338.     ioctl(fileno(stdin),TIOCGETP,&iobasic);
  339.     iobasic.sg_flags = oldflags;
  340.     ioctl(fileno(stdin),TIOCSETP,&iobasic);
  341.  
  342.     ioctl(fileno(stdin),TIOCGLTC,&termc);
  343.     termc.t_suspc = 26;
  344.     termc.t_dsuspc = 25;
  345.     ioctl(fileno(stdin),TIOCSLTC,&termc);
  346. }
  347.  
  348. newterm()
  349. {
  350.     ioctl(fileno(stdin),TIOCGETP,&iobasic);
  351.     oldflags = iobasic.sg_flags;
  352.     iobasic.sg_flags |= CBREAK;
  353.     iobasic.sg_flags &= ~ECHO;
  354.     ioctl(fileno(stdin),TIOCSETN,&iobasic);
  355.  
  356.     ioctl(fileno(stdin),TIOCGLTC,&termc);
  357.     termc.t_suspc = -1;
  358.     termc.t_dsuspc = -1;
  359.     ioctl(fileno(stdin),TIOCSLTC,&termc);
  360. }
  361.  
  362. extended_command()
  363. {
  364.     int cn, ref;
  365.  
  366.     printf(": ");
  367.     cn = getcom(cmds,ncmds,":");
  368.     printf("\n");
  369.     ref = sym_ref(cmds[cn]);
  370.     exec(ref);
  371. }
  372.  
  373. sym_ref(name)
  374. char *name;
  375. {
  376.     int ref;
  377.  
  378.     if (name == NULL) return(0);
  379.  
  380.     for (ref = 0;
  381.          symbol[ref].name != NULL && strcmp(name,symbol[ref].name);
  382.          ref++);
  383.  
  384.     if (symbol[ref].name != NULL) return(ref);
  385.     return(0);
  386. }
  387.  
  388. describe_key()
  389. {
  390.     char key;
  391.     int tab, ref;
  392.  
  393.     printf("describe-key: ");
  394.     key = getchar();
  395.  
  396.     switch (key) {
  397.         case 27: printf("ESC-");   tab = 1; break;
  398.         case 24: printf("CTL-X-"); tab = 2; break;
  399.         case 25: printf("CTL-Y-"); tab = 3; break;
  400.         default: put_char(key);    tab = 0; break;
  401.     }
  402.  
  403.     if (tab) {
  404.         key = getchar();
  405.         put_char(key);
  406.     }
  407.  
  408.     ref = binding[key][tab];
  409.     printf(" is bound to the command \"%s\"\n",symbol[ref].name);
  410. }
  411.  
  412. bind_key()
  413. {
  414.     char key;
  415.     int tab, ref, cn;
  416.  
  417.     printf("bind-key: ");
  418.     key = getchar();
  419.  
  420.     switch (key) {
  421.         case 27: printf("ESC-");   tab = 1; break;
  422.         case 24: printf("CTL-X-"); tab = 2; break;
  423.         case 25: printf("CTL-Y-"); tab = 3; break;
  424.         default: put_char(key);    tab = 0; break;
  425.     }
  426.  
  427.     if (tab) {
  428.         key = getchar();
  429.         put_char(key);
  430.     }
  431.  
  432.     printf(" to command: ");
  433.     cn = getcom(cmds,ncmds,"bind-key to command:");
  434.     printf("\n");
  435.     ref = sym_ref(cmds[cn]);
  436.     binding[key][tab] = ref;
  437. }
  438.  
  439. describe_bindings()
  440. {
  441.     int i, k, x, max;
  442.  
  443.     max = 0;
  444.     for (i = 1; i < ncmds; i++) {
  445.         x = strlen(cmds[i]);
  446.         if (x > max) max = x;
  447.     }
  448.  
  449.     for (i = 1; i < ncmds; i++) {
  450.         x = sym_ref(cmds[i]);
  451.         printf("%s",cmds[i]);
  452.         for (k = strlen(cmds[i]); k < max; k++) printf(" ");
  453.         printf("  ");
  454.  
  455.         for (k = 0; k < 128; k++)
  456.             if (binding[k][0] == x) {
  457.                 printf(" (");
  458.                 put_char(k);
  459.                 printf(")");
  460.             }
  461.         for (k = 0; k < 128; k++)
  462.             if (binding[k][1] == x) {
  463.                 printf(" (ESC-");
  464.                 put_char(k);
  465.                 printf(")");
  466.             }
  467.         for (k = 0; k < 128; k++)
  468.             if (binding[k][2] == x) {
  469.                 printf(" (CTL-X-");
  470.                 put_char(k);
  471.                 printf(")");
  472.             }
  473.         for (k = 0; k < 128; k++)
  474.             if (binding[k][3] == x) {
  475.                 printf(" (CTL-Y-");
  476.                 put_char(k);
  477.                 printf(")");
  478.             }
  479.         printf("\n");
  480.     }
  481. }
  482.  
  483. dump_symbol_table()
  484. {
  485.     int i;
  486.  
  487.     for (i = 0; i <= nsyms; i++) {
  488.         printf("%4d: %s ",i,symbol[i].name);
  489.         switch (symbol[i].type) {
  490.             case COMMAND:  printf("[command] "); break;
  491.             case VARIABLE: printf("[variable] "); break;
  492.             default: printf("[%d] ",symbol[i].type);
  493.         }
  494.         printf("\"%s\" %d\n",symbol[i].strval,symbol[i].value);
  495.     }
  496. }
  497. SHAR_EOF
  498. fi # end of overwriting check
  499. if test -f 'iface.h'
  500. then
  501.     echo shar: will not over-write existing file "'iface.h'"
  502. else
  503. cat << \SHAR_EOF > 'iface.h'
  504. #include <setjmp.h>
  505. #include <sgtty.h>
  506. #include <signal.h>
  507. #include <stdio.h>
  508. #define NSYM 256
  509. #define COMMAND 0
  510. #define VARIABLE 1
  511. extern char *cmds[256], *syms[NSYM], lastkey;
  512. extern int (*cptr[256])(), binding[128][4];
  513. extern int oldflags, ncmds, nsyms;
  514.  
  515. extern struct ltchars termc;
  516. extern struct sgttyb iobasic;
  517. jmp_buf topenv;
  518. void sigtrap();
  519. void addcom();
  520. char *strcpy();
  521.  
  522. struct sym_struct {
  523.     char *name,*strval;
  524.     int type,value;
  525. };
  526. extern struct sym_struct symbol[NSYM];
  527. SHAR_EOF
  528. fi # end of overwriting check
  529. if test -f 'fns.c'
  530. then
  531.     echo shar: will not over-write existing file "'fns.c'"
  532. else
  533. cat << \SHAR_EOF > 'fns.c'
  534. #include "iface.h"
  535.  
  536. do_something()
  537. {
  538.     long random();
  539.     int i;
  540.     char name[128];
  541.  
  542.     i = (int)(random() % 11);
  543.  
  544.     switch (i) {
  545.         case  0: printf("Hello World\n"); break;
  546.         case  1: printf("This space intentionally left blank\n"); break;
  547.         case  2: printf("***REPLACE THIS LINE WITH YOUR MESSAGE***\n"); break;
  548.         case  3: printf("Testing 1, 2, 3, 4\n"); break;
  549.         case  4: printf("Please ignore this message\n"); break;
  550.         case  5: printf("Error\07\n"); break;
  551.         case  6: printf("version 0.0\n"); break;
  552.         case  7: printf("What the hell is a Mimsey Tove?\n"); break;
  553.         case  8: printf("(core not dumped)\n"); break;
  554.         case  9: printf("[ynq] "); put_char(getchar()); printf("\n"); break;
  555.         case 10:
  556.             printf("Please enter your name: ");
  557.             get_string(name);
  558.             printf("\nThank you\n");
  559.             break;
  560.     }
  561. }
  562.  
  563. do_nothing() {printf("Done!\n");}
  564. SHAR_EOF
  565. fi # end of overwriting check
  566. if test -f 'init.c'
  567. then
  568.     echo shar: will not over-write existing file "'init.c'"
  569. else
  570. cat << \SHAR_EOF > 'init.c'
  571. #include "iface.h"
  572.  
  573. init()
  574. {
  575.     srandom(getpid());
  576.     signal(SIGINT,sigtrap);
  577.     signal(SIGHUP,sigtrap);
  578.     newterm();
  579.     init_symbols();
  580.     init_variables();
  581.     init_bindings();
  582. }
  583.  
  584. init_symbols()
  585. {
  586.     int i,j;
  587.     char *malloc();
  588.     int (*command_ptr())();
  589.  
  590.     for (i = 0; i < 128; i++)
  591.         for (j = 0; j < 4; j++) binding[i][j] = 0;
  592.  
  593.     nsyms = 0;
  594.     cmds[0] = malloc(6);
  595.     strcpy(cmds[0],"BOGUS");
  596.     cptr[0] = command_ptr("BOGUS");
  597.     symbol[0].name = cmds[0];
  598.     symbol[0].value = 0;
  599.     ncmds = 1;
  600.  
  601.     addcom("CTL-X-prefix");
  602.     addcom("CTL-Y-prefix");
  603.     addcom("ESC-prefix");
  604.     addcom("bind-key");
  605.     addcom("describe-bindings");
  606.     addcom("describe-key");
  607.     addcom("do-nothing");
  608.     addcom("do-something");
  609.     addcom("dump-symbol-table");
  610.     addcom("extended-command");
  611.     addcom("print-version");
  612.     addcom("quit");
  613. }
  614.  
  615. init_variables()
  616. {
  617.     addvar("dummy","",0);
  618.     addvar("version","0.0",0);
  619. }
  620.  
  621. void addcom(str)
  622. char *str;
  623. {
  624.     char *malloc();
  625.     int ref;
  626.  
  627.     if (strcmp(str,cmds[ncmds-1]) < 0) {
  628.         printf("# Yuck! initial command %s is out of place!\n",str);
  629.         quit();
  630.     }
  631.  
  632.     cmds[ncmds] = malloc((unsigned)(strlen(str)+1));
  633.     strcpy(cmds[ncmds],str);
  634.     cptr[ncmds] = command_ptr(str);
  635.     ncmds++;
  636.  
  637.     for (ref = 1; (ref < NSYM) && (symbol[ref].name != NULL); ref++);
  638.     symbol[ref].name = cmds[ncmds-1];
  639.     symbol[ref].type = COMMAND;
  640.     symbol[ref].value = ncmds-1;
  641.     addsym(symbol[ref].name);
  642. }
  643.  
  644. addvar(str,strval,val)
  645. char *str, *strval;
  646. int val;
  647. {
  648.     char *malloc();
  649.     int ref;
  650.  
  651.     for (ref = 1; (ref < NSYM) && (symbol[ref].name != NULL); ref++);
  652.     symbol[ref].name = malloc(strlen(str) + 1);
  653.     strcpy(symbol[ref].name,str);
  654.     symbol[ref].strval = malloc(strlen(strval) + 1);
  655.     strcpy(symbol[ref].strval,strval);
  656.     symbol[ref].type = VARIABLE;
  657.     symbol[ref].value = val;
  658.     addsym(str);
  659. }
  660.  
  661. int (*command_ptr(str))()
  662. char *str;
  663. {
  664.     int BOGUS(), CTL_X_prefix(), CTL_Y_prefix(), ESC_prefix();
  665.     int quit(), extended_command(), dump_symbol_table();
  666.     int describe_bindings(), describe_key(), bind_key(), print_version();
  667.     int do_something(), do_nothing();
  668.  
  669.     if (!strcmp(str,"BOGUS")) return(BOGUS);
  670.     if (!strcmp(str,"CTL-X-prefix")) return(CTL_X_prefix);
  671.     if (!strcmp(str,"CTL-Y-prefix")) return(CTL_Y_prefix);
  672.     if (!strcmp(str,"ESC-prefix")) return(ESC_prefix);
  673.     if (!strcmp(str,"bind-key")) return(bind_key);
  674.     if (!strcmp(str,"describe-bindings")) return(describe_bindings);
  675.     if (!strcmp(str,"describe-key")) return(describe_key);
  676.     if (!strcmp(str,"do-nothing")) return(do_nothing);
  677.     if (!strcmp(str,"do-something")) return(do_something);
  678.     if (!strcmp(str,"dump-symbol-table")) return(dump_symbol_table);
  679.     if (!strcmp(str,"extended-command")) return(extended_command);
  680.     if (!strcmp(str,"print-version")) return(print_version);
  681.     if (!strcmp(str,"quit")) return(quit);
  682.     return(BOGUS);
  683. }
  684.  
  685. addsym(str)
  686. char *str;
  687. {
  688.     int i, j, scan;
  689.     char *malloc();
  690.  
  691.     i = 0;
  692.     scan = 1;
  693.  
  694.     while ((scan) && (i < nsyms))
  695.         if (strcmp(str,syms[i]) < 0) scan = 0;
  696.         else i++;
  697.  
  698.     for (j = nsyms; j > i; j--) syms[j] = syms[j-1];
  699.  
  700.     syms[i] = malloc(strlen(str) + 1);
  701.     strcpy(syms[i],str);
  702.     nsyms++;
  703. }
  704.  
  705. init_bindings()
  706. {
  707.     binding[' '][0] = sym_ref("do-something");
  708.     binding['d'][0] = sym_ref("do-something");
  709.     binding['n'][0] = sym_ref("do-nothing");
  710.     binding['q'][0] = sym_ref("quit");
  711.     binding['x'][0] = sym_ref("extended-command");
  712.     binding['x'][1] = sym_ref("extended-command");
  713.     binding[24] [0] = sym_ref("CTL-X-prefix");
  714.     binding[25] [0] = sym_ref("CTL-Y-prefix");
  715.     binding[27] [0] = sym_ref("ESC-prefix");
  716.     binding[27] [1] = sym_ref("quit");
  717. }
  718. SHAR_EOF
  719. fi # end of overwriting check
  720. if test -f 'io.c'
  721. then
  722.     echo shar: will not over-write existing file "'io.c'"
  723. else
  724. cat << \SHAR_EOF > 'io.c'
  725. #include <stdio.h>
  726.  
  727. get_string(str)
  728. char *str;
  729. {
  730.     char c;
  731.     int i;
  732.  
  733.     i = 0;
  734.     str[i] = '\0';
  735.  
  736.     while ('\n' != (c = getchar())) {
  737.         switch (c) {
  738.         case 8: /* BACKSPACE */
  739.             if (i > 0) {
  740.                 if (str[i-1] < 32 || str[i-1] == 127) printf("\b \b");
  741.                 str[--i] = '\0';
  742.                 printf("\b \b");
  743.                 fflush(stdout);
  744.             }
  745.             break;
  746.         case 127: /* DEL */
  747.             for (i--; i > 0; i--) {
  748.                 if (str[i-1] < 32 || str[i-1] == 127) printf("\b \b");
  749.                 printf("\b \b");
  750.             }
  751.             str[0] = '\0';
  752.             fflush(stdout);
  753.             break;
  754.         default:
  755.             put_char(c);
  756.             str[i++] = c;
  757.             break;
  758.         }
  759.     }
  760.     str[i] = '\0';
  761. }
  762.  
  763. put_char(c)
  764. char c;
  765. {
  766.     if (c > 31) {
  767.         if (c == 127) printf("^?");
  768.         else printf("%c",c);
  769.     }
  770.     else printf("^%c",c+64);
  771. }
  772. SHAR_EOF
  773. fi # end of overwriting check
  774. if test -f 'iface.c'
  775. then
  776.     echo shar: will not over-write existing file "'iface.c'"
  777. else
  778. cat << \SHAR_EOF > 'iface.c'
  779. #include <setjmp.h>
  780. #include <sgtty.h>
  781. #include <signal.h>
  782. #include <stdio.h>
  783.  
  784. #define NSYM 256
  785. #define forever for(;;)
  786.  
  787. char *cmds[256], *syms[NSYM], lastkey;
  788. int (*cptr[256])(), binding[128][4];
  789. int oldflags, ncmds, nsyms;
  790.  
  791. struct ltchars termc;
  792. struct sgttyb iobasic;
  793. jmp_buf topenv;
  794. void sigtrap();
  795.  
  796. struct sym_struct {
  797.     char *name,*strval;
  798.     int type,value;
  799. };
  800. struct sym_struct symbol[NSYM];
  801.  
  802.  
  803. main()
  804. {
  805.     printf("Welcome to interface\n");
  806.     init();
  807.     print_version();
  808.     user_level();
  809.     exit(0);
  810. }
  811.  
  812. user_level()
  813. {
  814.     int ref;
  815.  
  816.     forever {
  817.         if (setjmp(topenv)) printf("top level\n");
  818.         lastkey = getchar();
  819.         ref = binding[lastkey][0];
  820.         exec(ref);
  821.     }
  822. }
  823.  
  824. void sigtrap(sig)
  825. int sig;
  826. {
  827.     switch(sig) {
  828.         case SIGINT:
  829.             printf("\nInterrupt\n");
  830.             longjmp(topenv,1);
  831.         case SIGHUP:
  832.             quit();
  833.     }
  834. }
  835. SHAR_EOF
  836. fi # end of overwriting check
  837. if test -f 'Makefile'
  838. then
  839.     echo shar: will not over-write existing file "'Makefile'"
  840. else
  841. cat << \SHAR_EOF > 'Makefile'
  842. CFLAGS = -O
  843. BIN=iface
  844.  
  845. iface: iface.o init.o fns.o exec.o iface.h comc.o io.o
  846.     cc -g -o ${BIN} iface.o init.o fns.o exec.o comc.o io.o
  847.  
  848. lint:
  849.     lint iface.c init.c fns.c exec.c iface.h comc.c io.c
  850. SHAR_EOF
  851. fi # end of overwriting check
  852. if test -f 'README'
  853. then
  854.     echo shar: will not over-write existing file "'README'"
  855. else
  856. cat << \SHAR_EOF > 'README'
  857. This directory contains the program iface.  Iface is a generic user interface,
  858. which supports:
  859.  
  860. - CBREAK mode terminal I/O
  861. - Keybindings for invoking top-level functions
  862. - extended-command function invocation
  863. - Name completion
  864.  
  865.  
  866. Internally, iface has the following structures:
  867.  
  868. - 4 keybinding tables for regular keys and ESC, CTL-X and CTL-Y prefix keys
  869. - A symbol table for command references
  870.  
  871.  
  872. The interface can be easily extended to any application by adding new functions
  873. in the file fns.c, adding the names to the symbol table in init_symbols in the
  874. file init.c, and adding a test to the name-to-function-pointer routine called
  875. command_ptr, in the file init.c.  Key bindings may be made in init_bindings.
  876.  
  877.  
  878. Several top-level functions exist.  They are:
  879.  
  880. BOGUS:  prints a BELL character (^G or \07) causing the terminal to feep.
  881.     generally used as a binding for otherwise unbound keys, or as an
  882.     error function.
  883.  
  884. CTL-X-prefix: switches to the CTL-X keymap and "executes" the next character.
  885.  
  886. CTL-Y-prefix: switches to the CTL-Y keymap and "executes" the next character.
  887.  
  888. ESC-prefix: switches to the ESC keymap and "executes" the next character.
  889.  
  890. bind-key: changes an entry in a keybinding table.
  891.  
  892. describe-bindings: prints a list of command names and associaled keybindings
  893.  
  894. describe-key: prints the command name associated with a key.
  895.  
  896. extended-command: allows command invocation by name.
  897.  
  898. quit: resets the terminal and exits.
  899.  
  900.  
  901. Two commands called "do-something" and "do-nothing" have been included in
  902. this distribution.  They are just there to demonstrate how new commands may
  903. be added.
  904.  
  905.  
  906. This interface has proven useful in developing several programs at UBC.  Have
  907. fun with it and feel free to add or change anything.  It is all public domain.
  908. Please leave my name attached.  Please don't sell it for profit.  Comments and
  909. suggestions are welcome.
  910.  
  911. ---
  912. Marc Majka  -  UBC Laboratory for Computational Vision
  913.  
  914. CDN:  majka@vision.ubc.cdn
  915. UUCP: majka@ubc-vision.uucp
  916. SHAR_EOF
  917. fi # end of overwriting check
  918. cd ..
  919. # End of shell archive
  920. exit 0
  921.  
  922.